#include "UART.h"
#include "Main/GateWay.h"

QReadWriteLock Log::lock;
UART::UART(QObject *parent)
    : BasePort(parent)
{
    uart = new QextSerialPort();  //新建串口类

    readTimer = new QTimer(this);
    readTimer ->setInterval(50);
    connect(readTimer, SIGNAL(timeout()), this, SLOT(readyReadSlot()));

    m_isSetEnablePin = false;
    m_readCount = 0;

    m_modeHash.insert("Polling",QextSerialBase::Polling);
    m_modeHash.insert("EventDriven",QextSerialBase::EventDriven);

    m_baudRateHash.insert("BAUD50",BAUD50);           //POSIX ONLY
    m_baudRateHash.insert("BAUD75",BAUD75);           //POSIX ONLY
    m_baudRateHash.insert("BAUD110",BAUD110);
    m_baudRateHash.insert("BAUD134",BAUD134);         //POSIX ONLY
    m_baudRateHash.insert("BAUD150",BAUD150);         //POSIX ONLY
    m_baudRateHash.insert("BAUD200",BAUD200);         //POSIX ONLY
    m_baudRateHash.insert("BAUD300",BAUD300);
    m_baudRateHash.insert("BAUD600",BAUD600);
    m_baudRateHash.insert("BAUD1200",BAUD1200);
    m_baudRateHash.insert("BAUD1800",BAUD1800);       //POSIX ONLY
    m_baudRateHash.insert("BAUD2400",BAUD2400);
    m_baudRateHash.insert("BAUD4800",BAUD4800);
    m_baudRateHash.insert("BAUD9600",BAUD9600);
    m_baudRateHash.insert("BAUD14400",BAUD14400);     //WINDOWS ONLY
    m_baudRateHash.insert("BAUD19200",BAUD19200);
    m_baudRateHash.insert("BAUD38400",BAUD38400);
    m_baudRateHash.insert("BAUD56000",BAUD56000);     //WINDOWS ONLY
    m_baudRateHash.insert("BAUD57600",BAUD57600);
    m_baudRateHash.insert("BAUD76800",BAUD76800);     //POSIX ONLY
    m_baudRateHash.insert("BAUD115200",BAUD115200);
    m_baudRateHash.insert("BAUD115200",BAUD115200);   //WINDOWS ONLY
    m_baudRateHash.insert("BAUD256000",BAUD256000);   //WINDOWS ONLY

    m_dataBitsHash.insert("DATA_5",DATA_5);
    m_dataBitsHash.insert("DATA_6",DATA_6);
    m_dataBitsHash.insert("DATA_7",DATA_7);
    m_dataBitsHash.insert("DATA_8",DATA_8);

    m_parityHash.insert("NONE", PAR_NONE);
    m_parityHash.insert("ODD",  PAR_ODD);
    m_parityHash.insert("EVEN", PAR_EVEN);
    m_parityHash.insert("MARK", PAR_MARK);    //WINDOWS ONLY
    m_parityHash.insert("SPACE",PAR_SPACE);

    m_stopBitsHash.insert("STOP_1",STOP_1);
    m_stopBitsHash.insert("STOP_1_5",STOP_1_5);    //WINDOWS ONLY
    m_stopBitsHash.insert("STOP_2",STOP_2);

    m_flowControlHash.insert("OFF",     FLOW_OFF);
    m_flowControlHash.insert("HARDWARE",FLOW_HARDWARE);
    m_flowControlHash.insert("XONXOFF", FLOW_XONXOFF);
}

void UART::setPortParam(PortStruct portParam)
{
    m_portParam = portParam;
    this->setObjectName(portParam.name());

    uart->setPortName(m_portParam.portName());
    uart->setQueryMode(m_modeHash.value(m_portParam.mode()));
    uart->setBaudRate(m_baudRateHash.value(m_portParam.baudRate()));             //波特率设置
    uart->setDataBits(m_dataBitsHash.value(m_portParam.dataBits()));               //数据位设置，我们设置为8位数据位
    uart->setParity(m_parityHash.value(m_portParam.parity()));               //奇偶校验设置，我们设置为无校验
    uart->setStopBits(m_stopBitsHash.value(m_portParam.stopBits()));               //停止位设置，我们设置为1位停止位
    uart->setFlowControl(m_flowControlHash.value(m_portParam.flowControl()));
    uart->setTimeout(10);
#ifdef Q_OS_LINUX
    if(!m_portParam.enablePinNumber().isEmpty())
    {
        this->m_isSetEnablePin = true;

        QString pinSetParam;

        pinSetParam = "echo  > /sys/class/gpio/export";
        pinSetParam.insert(5,m_portParam.enablePinNumber());
        system(pinSetParam.toLatin1().data());              //设置IO口

        pinSetParam = "echo out > /sys/class/gpio/gpio/direction";
        pinSetParam.insert(31,m_portParam.enablePinNumber());
        system(pinSetParam.toLatin1().data());              //设置IO口方向，输出

        pinSetParam = "echo 0 > /sys/class/gpio/gpio/value";
        pinSetParam.insert(29,m_portParam.enablePinNumber());
        system(pinSetParam.toLatin1().data());            //设置IO口电平，低电平

    }
#endif
}



void UART::open()
{
    uart->open(QIODevice::ReadWrite);
    readTimer->start();
}

void UART::close()
{
    uart->close();
    readTimer->stop();
}

void UART::readyReadSlot()
{
    QByteArray data = uart->readAll();
    QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    if(!data.isEmpty())
    {
        m_readCount++;
        m_readData.append(data);
        if(m_readCount >= 4)
        {
            m_readCount = 0;

            qDebug()<<"Read<-- "<<m_portParam<<"data:"<<DataTypeConver::formatString(m_readData);
            Log::lock.lockForWrite();
            Log::writeToLog(time,"Read<--"+m_portParam.name()+"/"+m_portParam.name()+" data: "+DataTypeConver::formatString(m_readData));
            Log::lock.unlock();
      //      qDebug()<<"UART 1 runing now";
            emit receiveDataSignal(m_portParam,m_readData);
            m_readData.clear();
        }
    }
    else if(data.isEmpty() && m_readCount>0)
    {
        m_readCount = 0;

        qDebug()<<"Read<-- "<<m_portParam<<"data:"<<DataTypeConver::formatString(m_readData);
        Log::lock.lockForWrite();
         Log::writeToLog(time,"Read<--"+m_portParam.name()+"/"+m_portParam.name()+" data: "+DataTypeConver::formatString(m_readData));
         Log::lock.unlock();
  //      qDebug()<<"UART 2 runing now";
        emit receiveDataSignal(m_portParam,m_readData);
        m_readData.clear();
    }
}
void UART::write(PortStruct target, QByteArray data)
{
#ifdef Q_OS_LINUX
     QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    if(m_isSetEnablePin)
    {
//      QString pinSetParam;
//      pinSetParam = "echo 1 > /sys/class/gpio/gpio/value";
//      pinSetParam.insert(29,m_portParam.enablePinNumber());
//      system(pinSetParam.toLatin1().data());  //设置IO口电平，高电平

        uart->write(data);
       qDebug()<<"Write-->"<<target<<"data:"<<DataTypeConver::formatString(data);
       Log::lock.lockForWrite();
       Log::writeToLog(time,"Write-->"+target.name()+" data: "+DataTypeConver::formatString(data));
       Log::lock.unlock();

      QElapsedTimer delayTimer;             //need delayTime don't cut

      delayTimer.start();
      while(delayTimer.elapsed()<=100);

//       pinSetParam = "echo 0 > /sys/class/gpio/gpio/value";
//       pinSetParam.insert(29,m_portParam.enablePinNumber());
//       system(pinSetParam.toLatin1().data());  //设置IO口电平，低电平
    }
    else
    {
        uart->write(data);
        qDebug()<<"Write-->"<<target<<"data:"<<DataTypeConver::formatString(data);
        Log::lock.lockForWrite();
        Log::writeToLog(time,"Write-->"+target.name()+" data: "+DataTypeConver::formatString(data));
        Log::lock.unlock();
//        /*-------------------qdebug------------------------*/
//        static QMutex mutex;
//        mutex.lock();
//        QString text;
//        QString currentTime = QDateTime::currentDateTime().toString("[MM-dd hh:mm:ss]");
//        text = currentTime +"Read-"+target.type()+"-"+target.name()+"-"+target.ip()+"-"+target.port()+"-data="+ DataTypeConver::formatString(data) + "\r\n"+"\r\n";
//        QByteArray textArray = text.toLatin1();
//        fprintf(stderr, textArray.constData());

//        QFile file(QCoreApplication::applicationDirPath() + "/Port.txt");
//        file.open(QIODevice::WriteOnly | QIODevice::Append);
//        QTextStream textStream(&file);
//        textStream << text;
//        file.flush();
//        file.close();

//        mutex.unlock();
//         /*-------------------------------------------*/
        QElapsedTimer delayTimer;
        delayTimer.start();
        while(delayTimer.elapsed()<=100);
    }
#endif

#ifdef Q_OS_WIN
        uart->write(data);
        qDebug()<<"Write-->"<<target<<"data:"<<DataTypeConver::formatString(data);
        QElapsedTimer delayTimer;
        delayTimer.start();
        while(delayTimer.elapsed()<=100);
#endif
}

UART::~UART()
{

}


